<template>
	<div id="cif-container-wrapper" class="container-wrapper" :style="state.contentStyle">
		<div id="cif-cpnt-container" ref="cpntContainer" class="cpnt-container" :style="styleName">
			<EngineFrame class="engine-frame" />
			<!-- <div class="grade" v-if="gradeFlag || cpntFrame.config.gradeShow" :style="gradeLenStyle"></div> -->
			<template v-for="cpntTreeNode in cpntNavTree" :key="cpntTreeNode.uuid">
				<ComponentWrapper
					v-if="!cpntTreeNode.isBroken"
					:ref="getWrapperRefName(cpntTreeNode)"
					:cpnt="cpntTreeNode"
					:on-relative="onRelative"
					:emit="emit"
					@contextmenu.prevent="cpntFrame.handleContextMenu($event, cpntTreeNode)" />
			</template>
		</div>
	</div>
</template>

<script lang="ts" setup>
import { onMounted, reactive, toRefs, computed, provide, inject, watch } from 'vue';
import ComponentWrapper from './ComponentWrapper.vue';
import EngineFrame from '@CIF/Runtime/Renderer/EngineFrame.vue';
import { CPNT_REF_PREFIX_ENUM } from '@CIF/Runtime/Global/variable';
import { ComponentTreeHelper } from '@CIF/ComponentTemplate/componentTree';
import elementResizeDetectorMaker from 'element-resize-detector';
import _ from 'lodash';
import { usePrimaryStore } from '@/store';

// const renderer = inject('renderer');
const cpntFrame: any = inject('cpntFrame');

const store = usePrimaryStore();
// const props = defineProps({
// 	props: {
// 		type: Object,
// 		default() {
// 			return {};
// 		}
// 	},
// 	option: Object,
// 	wscale: Number
// });
const cpntNavTree = computed(() => {
	return store.getCpntTree;
});
watch(
	() => store.cpntTree,
	(newTree) => {
		console.log('------------------------------------newTree', newTree);
		// cpntNavTree.value = newTree;
	},
	{ deep: true }
);
const state = reactive({
	containerwidth: 0,
	containerheight: 0,
	contentStyle: {},
	selectCount: {
		x1: null,
		x2: null,
		y1: null,
		y2: null
	},
	scale: 1,
	gradeFlag: false,
	cpntWrapperRefMap: new Map()
});
//计算中央可视化大屏比例
const styleName = computed(() => {
	const canvasSize = store.getRendererCanvasSize;

	return { ...canvasSize };
});

function getWrapperRefName(cpnt: any) {
	if (!_.isEmpty(cpnt.componentInstance)) {
		return CPNT_REF_PREFIX_ENUM.CPNT_WRAPPER + cpnt.componentInstance.uuid;
	} else {
		return '';
	}
}

/**
 * 该方法用于组件通知 CIF更新回调对象，更新结果会显示在 callbackValues 中
 * data = {K1: 12345, K2: 34567}
 * @param id: 组件 id
 * @param data: 要更新的回调对象
 */
function onRelative(id: any, data: any) {
	if (typeof data !== 'object') {
		return false;
	}
	if (_.get(window, 'cif.config.logger.enable', false) === true) {
		console.log('CIF.R.R.ComponentContainer:onRelative 有组件正在注入data', data);
	}
	const cpntTreeNode = ComponentTreeHelper.findTreeNodeQuick(id);
	const instance = _.get(cpntTreeNode, 'componentInstance');
	if (_.isEmpty(instance)) {
		return;
	}
	const callbackArgs = _.get(instance, 'callbackArgs', []);

	for (const [target, value] of Object.entries(data)) {
		// callbackArgs中的target是不允许重复的
		// 因为不允许将不同的字段值映射到相同的变量名上

		const targetCallback = callbackArgs.find((callbackArg: any) => {
			if (callbackArg.target === target) {
				return true;
			}
		});
		if (!_.isEmpty(targetCallback)) {
			if (_.get(window, 'cif.config.logger.enable', false) === true) {
				console.log('CIF.R.R.ComponentContainer:onRelative 需要触发', target, '值的变化', value);
			}

			// 根据listenser将数据分发到各个组件
			store.getCallbackListeners(target).forEach((cpntId: any) => {
				// 需要改
				store.updateCallbackPool({
					target,
					origin: _.get(targetCallback, 'origin'),
					originCpnt: instance.uuid,
					value
				});

				const wrapper = getCpntWrapperById(cpntId);
				wrapper.exposed.updateCallbackValues(target, value);
			});
		}
	}
	// TODO: 回调更新
	// if (_.isPlainObject(data)) {
	//   // 1. 用 Object.keys 遍历data中的数据，逐一赋值，整体更新
	//   const clonedPool = _.cloneDeep(this.callbackValuePool)
	//   Object.keys(data).forEach(key => {
	//     clonedPool[key] = data[key]
	//   })
	//   this.callbackValuePool = clonedPool
	// }
}
function getCpntWrapperById(cpntId: any) {
	return state.cpntWrapperRefMap.get(cpntId);
	// 通过 DOM id 来获取 VUE 组件实例没走通，未查询到示例，初步结论不可行
	// return this.$refs[`${CPNT_REF_PREFIX_ENUM.CPNT_WRAPPER}${cpntId}`][0]
}
/**
 * 该方法用于组件通知 CIF 触发了哪些自定义事件
 * @param eventName: 组件在主配置文件中定义的 events
 * @param data: data 在 emit 中被用于条件判断。比如，当事件触发后，自定义事件中的条件判断为 s==1，那么 emit 会检测 data 中 s 的值是否满足该条件
 * @param cmponentId: 发送事件的组件的 id，如果没有子组件，则可不传，不传为当前组件 id，如果有子组件，不传则为父组件 id，如果是子组件则必须传子组件的 id.
 *
 */
function emit(eventName: any, data: any, componentId: any, filter: any) {
	const eventCpntWrapper = getCpntWrapperById(componentId);

	let interactions = _.get(eventCpntWrapper, 'ctx.cpnt.componentInstance.interactions').filter(
		(interaction: any) => _.isEqual(eventName, interaction.event)
	);
	// TODO: 自定义事件的条件判断逻辑
	// if data === s
	if (!_.isNil(filter) && typeof filter === 'function') {
		interactions = filter(interactions);
	}
	for (const interaction of interactions) {
		const actionCpntIdArr = interaction.cpntIds;
		const action = interaction.action;
		const actionConfig = interaction.actionConfig;
		const event = {
			eventName: eventName,
			payload: data,
			config: actionConfig
		};

		for (const actionCpntId of actionCpntIdArr) {
			try {
				// const actionCpntVueInst = getCpntWrapperById(actionCpntId).getCpntVueInst();
				const actionCpntVueInst = getCpntWrapperById(actionCpntId).refs.cpntInst;
				console.log('aaaaactionCpntVueInst)', actionCpntVueInst, 'action', action, 'event,', event);
				actionCpntVueInst[action](event);
			} catch (e) {
				if (_.get(window, 'cif.config.logger.enable', false) === true) {
					console.log(
						`CIF.R.R.ComponentContainer:emit Error execute ${eventName} action on component ${actionCpntId}, maybe ${action} is not defined in it`,
						e
					);
				}
			}
		}
	}
}

// 需要在 ComponentWrapper 里调用
function registerCpntRef(cpntId: any, ref: any) {
	if (_.get(window, 'cif.config.logger.enable', false) === true) {
		console.log(`CIF.R.R.ComponentContainer:registerCpntRef ${cpntId}`, ref);
	}
	state.cpntWrapperRefMap.set(cpntId, ref);
}

onMounted(() => {
	const erdUltraFast = elementResizeDetectorMaker({
		strategy: 'scroll' //<- For ultra performance.
	});
	erdUltraFast.listenTo(document.getElementById('cif-cpnt-container'), (element: any) => {
		state.containerwidth = element.offsetWidth;
		state.containerheight = element.offsetHeight;
		store.setContainerSize(element);
	});
});
defineExpose({ ...toRefs(state), getCpntWrapperById });
provide('cpntContainer', { state, registerCpntRef, getWrapperRefName, getCpntWrapperById });
</script>

<style lang="scss" scoped>
.container-wrapper {
	width: 100%;
	height: 100%;
	position: relative;
	box-sizing: border-box;
	background-color: rgba(0, 0, 0, 0.8);
	flex: 1;
	transform-origin: 0 0;
	box-sizing: border-box;
}
// .container-wrapper::-webkit-scrollbar {
// 	width: 6px; /* 设置滚动条宽度为6px */
// }

// .container-wrapper::-webkit-scrollbar-track {
// 	background-color: transparent; /* 设置滚动条背景颜色为浅灰色 */
// }

// .container-wrapper::-webkit-scrollbar-thumb {
// 	background-color: #555555; /* 设置滚动条滑块颜色为黑灰色 */
// }

// .container-wrapper:hover::-webkit-scrollbar-thumb {
// 	background-color: #555555; /* 悬浮时设置滚动条滑块颜色为更深的黑色 */
// }

.cpnt-container {
	/* width: 100%;
  height: 100%; */
	user-select: none; // 防止选取 <div> 元素的文本：
	transform-origin: 0 0;
	overflow: auto;
	position: relative;
}

.engine-frame {
	width: 100%;
	height: 100%;
	position: absolute !important;
	top: 0;
	left: 0;
	/* z-index: 0; */
}

.footer__menu {
	padding-top: 8px;
	margin-right: 370px;
	float: right;
	width: 300px;
}
.app--none {
	padding: 0;
	height: 100%;
}
.app--none .wrapper {
	position: relative;
	padding: 0;
	margin: 0 auto;
	width: 100%;
}
.app--none .content {
	width: 100%;
	height: 100%;
	border: none;
}
.grade {
	width: 100%;
	height: 100%;
	background-size:
		30px 30px,
		30px 30px;
	background-image: linear-gradient(rgba(255, 255, 255, 0.1) 1px, transparent 0px),
		linear-gradient(90deg, rgba(255, 255, 255, 0.1) 1px, transparent 0px);
	position: absolute;
	top: 0;
	bottom: 0;
	left: 0;
	right: 0;
}
</style>
